package com.threegold.listview;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.app.Context;

import java.util.ArrayList;
import java.util.List;

class Row extends DirectionalLayout implements ComponentContainer.ArrangeListener, Component.DrawTask {

    private final List<Component> itemChildren = new ArrayList<>();
    /**
     * 是否已经第一次执行了布局排布
     */
    private boolean hasInitArrange;

    /**
     * 是否是最后一行
     */
    private boolean isLastRow;
    /**
     * 是否是第一行
     */
    private boolean isFirstRow;
    /**
     * 当前展示的列数
     */
    private int displayColumn;
    /**
     * 最大展示的列数，也就是row展示的总列数
     */
    private int columnNo;
    /**
     * 绘制垂直分割线的矩形对象
     */
    private final Rect rowDividerRect = new Rect();
    /**
     * 绘制垂直分割线的画笔
     */
    private final Paint paint = new Paint();

    private final Builder builder;

    private Row(Context context, Builder builder) {
        super(context);
        this.builder = builder;
        // 设置画笔属性和颜色
        paint.setAntiAlias(true);
        paint.setColor(new Color(builder.rowDividerColor));
        // 强制水平排列
        setOrientation(HORIZONTAL);
        // 设置布局排列监听
        setArrangeListener(this);
        // 设置绘制监听
        addDrawTask(this);
    }

    public boolean isShowColumnOuterDivider() {
        return builder.showColumnOuterDivider;
    }

    public int getColumnDividerWidth() {
        return builder.columnDividerSize;
    }

    /**
     * 刷新效果：根据当前排列展示的数据进行重绘和隐藏不需要的列item
     * @param lastRow 是否是最后一行
     * @param firstRow 是否是第一行
     * @param columnNo 当前能够展示的总列数
     * @param displayColumn 当前展示的列数
     */
    public void refreshEffect(boolean lastRow, boolean firstRow, int columnNo, int displayColumn) {
        this.isLastRow = lastRow;
        this.isFirstRow = firstRow;
        this.columnNo = columnNo;
        this.displayColumn = displayColumn;
        // 隐藏该隐藏的分割线
        for (int i = 0; i < getChildCount(); i++) {
            Component component = getComponentAt(i);
            if (component instanceof Divider) {
                // 计算divider对应的column索引
                int matchItemIndex = (i + 1) / 2;
                if (isLastRow) {
                    // 如果divider对应的column索引小于等于displayColumn，则可显示，否则隐藏
                    component.setVisibility(matchItemIndex <= displayColumn ? VISIBLE : INVISIBLE);
                } else {
                    component.setVisibility(VISIBLE);
                }
            }
        }
        // 设置bottomPadding为垂直方向的分割线高度，目的是为了让这个padding站位，然后再对应的矩形位置进行绘制分割线，达到设置分割线的效果
        // 只有第一行会绘制顶部的分割线，因此只有第一行且需要绘制分割线才设置topPadding
        setPaddingTop((isFirstRow && builder.showTopRowDivider) ? builder.rowDividerSize : 0);
        // 只有最后一行且不需要绘制底部分割线才不需要设置bottomPadding
        setPaddingBottom(isLastRow && !builder.showBottomDivider ? 0 : builder.rowDividerSize);
        // 重绘：可以刷新垂直分割线的绘制
        invalidate();
    }

    public void addRowItemChild(Component rowItem, boolean isFirstColumn, boolean lastColumn) {
        // 添加rowItem到集合，用于屏蔽分割线获取每一行的rowItem
        itemChildren.add(rowItem);
        // 修改布局参数，多列时候每一个rowItem宽度都是weight=1，宽度均分
        LayoutConfig layoutConfig = (LayoutConfig) rowItem.getLayoutConfig();
        layoutConfig.weight = 1;
        layoutConfig.width = 0;
        rowItem.setLayoutConfig(layoutConfig);
        addComponent(rowItem);
        // 添加分割线：除了当前行最后一列，其余都要添加
        if (builder.columnDividerSize <= 0) {
            return;
        }
        if (builder.showColumnOuterDivider) {
            // 所有的item都要添加右边的分割线，且第一个item需要添加左边的分割线
            if (isFirstColumn) {
                insertDividerToFirst();
            }
            addDividerToItemRight();
        } else {
            // 除了最后一个item，都要添加右边的分割线
            if (!lastColumn) {
                addDividerToItemRight();
            }
        }
    }

    private Divider createColumnDivider() {
        LayoutConfig dividerLc = new LayoutConfig(builder.columnDividerSize, 0);
        Divider divider = new Divider(getContext());
        divider.setLayoutConfig(dividerLc);
        ShapeElement bg = new ShapeElement();
        bg.setRgbColor(RgbColor.fromArgbInt(builder.columnDividerColor));
        divider.setBackground(bg);
        return divider;
    }

    private void addDividerToItemRight() {
        addComponent(createColumnDivider());
    }

    private void insertDividerToFirst() {
        addComponent(createColumnDivider(), 0);
    }

    public Component getItemChild(int position) {
        return itemChildren.get(position);
    }

    @Override
    public boolean onArrange(int left, int top, int width, int height) {
        if (!hasInitArrange) {
            hasInitArrange = true;
            calculateHorizontalDividerHeight(height);
        }
        return false;
    }

    /**
     * 添加的时候当前行的布局参数为MATCH_CONTENT，具体高度值还未计算出，水平方向的分割线高度就不能够确定，
     * 第一次布局排布时候，拿到高度并且将水平分割线的高度设置为当前行高度
     */
    private void calculateHorizontalDividerHeight(int height) {
        for (int i = 0; i < getChildCount(); i++) {
            Component component = getComponentAt(i);
            if (component instanceof Divider) {
                ComponentContainer.LayoutConfig layoutConfig = component.getLayoutConfig();
                layoutConfig.height = height;
                component.setLayoutConfig(layoutConfig);
            }
        }
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        // 垂直分割线的尺寸小于等于0，不绘制
        if (builder.rowDividerSize <= 0) {
            return;
        }
        // row的宽度
        int estimatedWidth = getEstimatedWidth();
        // 默认认为当前行展示的列等于总列数，绘制宽度为row宽度
        int drawWidth = estimatedWidth;
        if (displayColumn < columnNo && !builder.rowDividerIgnoreDisplayColumn) {
            // 计算展示列小于总列数的绘制宽度
            // 获取当前行所有item的宽度总和
            int itemTotalWidth = estimatedWidth - (columnNo - 1) * builder.columnDividerSize;
            // 一个item的宽度
            float perItemWidth = 1.0f * itemTotalWidth / columnNo;
            // 绘制的宽度 = displayColumn * (perItemWidth + columnDividerSize)
            drawWidth = (int) ((perItemWidth + builder.columnDividerSize) * displayColumn);
        }

        // 绘制分割线时候换个思路，不判断isLastRow和isFirstRow，直接获取topPadding和bottomPadding，有值就绘制，没有值就不绘制
        int paddingTop = getPaddingTop();
        if (paddingTop > 0) {
            rowDividerRect.set(0, 0 , drawWidth, builder.rowDividerSize);
            canvas.drawRect(rowDividerRect, paint);
        }
        int paddingBottom = getPaddingBottom();
        if (paddingBottom > 0) {
            // row的高度
            int estimatedHeight = getEstimatedHeight();
            rowDividerRect.set(0, estimatedHeight - builder.rowDividerSize , drawWidth, estimatedHeight);
            canvas.drawRect(rowDividerRect, paint);
        }
    }

    /**
     * 自定义Divider类，目的是为了循环遍历子组件时候，更方便判断该组件为分割线，没有其他作用
     */
    private static class Divider extends Component {
        public Divider(Context context) {
            super(context);
        }
    }

    public static class Builder {

        private final Context context;
        /**
         * 列（即垂直）分割线的颜色
         */
        private int columnDividerColor;
        /**
         * 列（即垂直）分割线的尺寸
         */
        private int columnDividerSize;
        /**
         * 多列的时候是否显示行左右的分割线
         */
        private boolean showColumnOuterDivider;
        /**
         * 行（即水平）分割线的颜色
         */
        private int rowDividerColor;
        /**
         * 行（即水平）分割线的尺寸
         */
        private int rowDividerSize;
        /**
         * 是否展示顶部分割线：只有当前row为第一个item的时候才生效
         */
        private boolean showTopRowDivider;
        /**
         * 是否展示底部分割线：只有当前row为最后一个item的时候才生效
         */
        private boolean showBottomDivider;
        /**
         * 绘制行分割线是否忽略当前行实际展示的列数：也就是每一行是否完整绘制行分割线
         * false：则行的开头和结尾都会绘制分割线。
         * true：则行的开头和结尾都不会绘制分割线。
         */
        private boolean rowDividerIgnoreDisplayColumn;

        public Builder(Context context) {
            this.context = context;
        }

        public Builder setColumnDividerColor(int columnDividerColor) {
            this.columnDividerColor = columnDividerColor;
            return this;
        }

        public Builder setColumnDividerSize(int columnDividerSize) {
            this.columnDividerSize = columnDividerSize;
            return this;
        }

        public Builder setShowColumnOuterDivider(boolean showColumnOuterDivider) {
            this.showColumnOuterDivider = showColumnOuterDivider;
            return this;
        }

        public Builder setRowDividerColor(int rowDividerColor) {
            this.rowDividerColor = rowDividerColor;
            return this;
        }

        public Builder setRowDividerSize(int rowDividerSize) {
            this.rowDividerSize = rowDividerSize;
            return this;
        }

        public Builder setShowTopRowDivider(boolean showTopRowDivider) {
            this.showTopRowDivider = showTopRowDivider;
            return this;
        }

        public Builder setShowBottomDivider(boolean showBottomDivider) {
            this.showBottomDivider = showBottomDivider;
            return this;
        }

        public Builder setRowDividerIgnoreDisplayColumn(boolean rowDividerIgnoreDisplayColumn) {
            this.rowDividerIgnoreDisplayColumn = rowDividerIgnoreDisplayColumn;
            return this;
        }

        public Row build() {
            return new Row(context, this);
        }
    }
}
